package com.huishi.ui.server;

import com.alibaba.fastjson.JSON;
import com.huishi.entity.*;
import com.huishi.entity.vo.FileMetaDataVO;
import com.huishi.entity.vo.PlacingFileTaskVO;
import com.huishi.entity.vo.UploadMsgVO;
import com.huishi.handler.execute.PlacingFilesService;
import com.huishi.handler.ws.MyWebSocketClient;
import com.huishi.mapper.*;
import com.huishi.ui.FileChooserUI;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.java_websocket.client.WebSocketClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.swing.*;
import java.awt.*;
import java.net.URISyntaxException;
import java.net.UnknownHostException;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ScheduledExecutorService;

@Slf4j
@Component
public class FileChooserUIServer {

    @Autowired
    private MyWebSocketClient myWebSocketClient;
    @Autowired
    private WebSocketClient webSocketClient; // 后台ws客户端
    @Autowired
    private PlacingFilesService placingFilesService;
    @Autowired
    private ScheduledExecutorService scheduler;
    @Autowired
    private PlacingFileTaskMapper placingFileTaskMapper;


    @Autowired
    private DictDataSourceMapper dictDataSourceMapper;
    @Autowired
    private DictTargetMapper dictTargetMapper;
    @Autowired
    private DictPwdFormatMapper dictPwdFormatMapper;
    @Autowired
    private DictGatherMapper dictGatherMapper;
    @Autowired
    private DictSystemModelMapper dictSystemModelMapper;

    // UI组件 start
    private JComboBox<DictDataSource> dataSourceJComboBox;
    private JComboBox<DictTarget> targetObjectComboBox;
    private JComboBox<DictPwdFormat> pdwComboBox;
    private JComboBox<DictGather> gatherPlaceComboBox;
    private JComboBox<DictSystemModel> systemModelComboBox;
    // UI组件 end

    public void setComponent(FileChooserUI fileChooserUI) {
        this.dataSourceJComboBox = fileChooserUI.getDataSourceComboBox();
        this.targetObjectComboBox = fileChooserUI.getTargetObjectComboBox();
        this.pdwComboBox = fileChooserUI.getPdwComboBox();
        this.gatherPlaceComboBox = fileChooserUI.getGatherPlaceComboBox();
        this.systemModelComboBox = fileChooserUI.getSystemModelComboBox();
    }

    /**
     * 处理落盘文件信息：实时更新程序上传数据包括速率不等，同步上传进度到后台汇总展示
     */
    public void processUploadMsg(FileChooserUI fileChooserUI) {
        if (webSocketClient.isClosed()) {
            log.debug("webSocketClient is closed");
            try {
                webSocketClient = myWebSocketClient.getClient();
            } catch (UnknownHostException | URISyntaxException e) {
                throw new RuntimeException(e);
            }
            webSocketClient.connect();
        }

        // 在Swing 的事件分派线程中更新标签文本
        SwingUtilities.invokeLater(() -> {
            UploadMsgVO uploadMsg = new UploadMsgVO();

            uploadMsg.setTaskName(fileChooserUI.taskNameField.getText());

            Integer fileNums = fileChooserUI.getFileNums();
            if (fileNums != null) {
                fileChooserUI.getFileNumLabel().setText("文件数：" + fileNums);
                uploadMsg.setFileNums(fileNums);
            }
            Double fileTotalSize = fileChooserUI.getFileTotalSize();
            if (fileTotalSize != null) {
//                fileChooserUI.getFileTotalSizeLabel().setText("文件大小：" + String.format("%.1f", fileTotalSize) + "MB");
                String fileTotalSizeText = fileChooserUI.getFileTotalSizeLabel().getText().split("：")[1];
//                uploadMsg.setFileTotalSize(String.format("%.1f", fileTotalSize) + "MB");
                uploadMsg.setFileTotalSize(fileTotalSizeText);
            }
            Double speed = fileChooserUI.getSpeed();
            if (speed != null) {
                fileChooserUI.getSpeedLabel().setText("速率：" + String.format("%.2f", speed) + "MB/S");
                uploadMsg.setSpeed(String.format("%.2f", speed) + "MB/S");
            }
            Long takeTime = fileChooserUI.getTakeTime();
            if (takeTime != null) {
                fileChooserUI.getTakeTimeLabel().setText("用时：" + takeTime / 1000 + "s");
                uploadMsg.setTakeTime(takeTime / 1000 + "s");
            }
            Double leftTime = fileChooserUI.getLeftTime();
            if (leftTime != null) {
                fileChooserUI.getLeftTimeLabel().setText("剩余时间：" + String.format("%.2f", leftTime) + "s");
                uploadMsg.setLeftTime(String.format("%.2f", leftTime) + "s");
            }
            uploadMsg.setProcess(fileChooserUI.getProgressBar().getValue());
            uploadMsg.setUserName(fileChooserUI.getUserNameField().getText());

            // 将上传进度信息通过ws发给后台
            webSocketClient.send(JSON.toJSONString(uploadMsg));
        });
    }


    /**
     * 处理未完成的落盘文件任务(因为程序中断等原因中断的任务)
     *
     * @return
     */
    public void processUnFinishedTask(FileChooserUI fileChooserUI) {
        List<PlacingFileTaskVO> unFinishedTasks = placingFileTaskMapper.checkUnFinishedTask();

        // 上传中断
        if (!unFinishedTasks.isEmpty()) {
            PlacingFileTaskVO placingFileTask = unFinishedTasks.get(0);
            fileChooserUI.setUnFinishedTaskId(placingFileTask.getId());

            fileChooserUI.folderPathField.setText(placingFileTask.getDirPath());
            fileChooserUI.taskNameField.setText(placingFileTask.getTaskName());

            // 设置下拉框之前选中的值=====
            Long systemModelId = placingFileTask.getSystemModelId();
            if (systemModelId != null) {
                for (int i = 0; i < systemModelComboBox.getItemCount(); i++) {
                    if (systemModelId.equals(systemModelComboBox.getItemAt(i).getId())) {
                        systemModelComboBox.setSelectedIndex(i);
                        break;
                    }
                }
            }

            Long gatherId = placingFileTask.getGatherId();
            if (gatherId != null) {
                for (int i = 0; i < gatherPlaceComboBox.getItemCount(); i++) {
                    if (gatherId.equals(gatherPlaceComboBox.getItemAt(i).getId())) {
                        gatherPlaceComboBox.setSelectedIndex(i);
                        break;
                    }
                }
            }

            Long targetId = placingFileTask.getTargetId();
            if (targetId != null) {
                for (int i = 0; i < targetObjectComboBox.getItemCount(); i++) {
                    if (targetId.equals(targetObjectComboBox.getItemAt(i).getId())) {
                        targetObjectComboBox.setSelectedIndex(i);
                        break;
                    }
                }
            }

            // 设置下拉框之前选中的值=====
            fileChooserUI.getProcessLogField().setText(placingFileTask.getProcessLog());

            Map<Integer, JTextField> customColumnVs = fileChooserUI.getCustomColumnVs();
            JPanel comBox5 = fileChooserUI.getComBox5();

            if (StringUtils.isNotEmpty(placingFileTask.getCustomColumn1())) {
                comBox5.add(new JLabel("  自定义字段1:"));
                JTextField jTextField = new JTextField(placingFileTask.getCustomColumn1(), 10);
                comBox5.add(jTextField);
                customColumnVs.put(1, jTextField);
            }
            if (StringUtils.isNotEmpty(placingFileTask.getCustomColumn2())) {
                comBox5.add(new JLabel("  自定义字段2:"));
                JTextField jTextField = new JTextField(placingFileTask.getCustomColumn2(), 10);
                comBox5.add(jTextField);
                customColumnVs.put(2, jTextField);
            }
            if (StringUtils.isNotEmpty(placingFileTask.getCustomColumn3())) {
                comBox5.add(new JLabel("  自定义字段3:"));
                JTextField jTextField = new JTextField(placingFileTask.getCustomColumn3(), 10);
                comBox5.add(jTextField);
                customColumnVs.put(3, jTextField);

                comBox5.add(new JLabel("           " +
                        "                           "));
            }
            if (StringUtils.isNotEmpty(placingFileTask.getCustomColumn4())) {
                comBox5.add(new JLabel("  自定义字段4:"));
                JTextField jTextField = new JTextField(placingFileTask.getCustomColumn4(), 10);
                comBox5.add(jTextField);
                customColumnVs.put(4, jTextField);

                Dimension newSize = new Dimension(fileChooserUI.getWidth(), fileChooserUI.getHeight() + 30);
                fileChooserUI.setPreferredSize(newSize);
                fileChooserUI.revalidate(); // 重新验证布局
                fileChooserUI.repaint();    // 重新绘制界面

            }
            if (StringUtils.isNotEmpty(placingFileTask.getCustomColumn5())) {
                comBox5.add(new JLabel("  自定义字段5:"));
                JTextField jTextField = new JTextField(placingFileTask.getCustomColumn5(), 10);
                comBox5.add(jTextField);
                customColumnVs.put(5, jTextField);
            }
            if (StringUtils.isNotEmpty(placingFileTask.getCustomColumn6())) {
                comBox5.add(new JLabel("  自定义字段6:"));
                JTextField jTextField = new JTextField(placingFileTask.getCustomColumn6(), 10);
                comBox5.add(jTextField);
                customColumnVs.put(6, jTextField);
            }


            // 强制重新布局和绘制
//            comBox5.revalidate();
//            comBox5.repaint();
//            fileChooserUI.revalidate();
//            fileChooserUI.repaint();
        }

    }


    /**
     * 初始并填充下拉框
     */
    public void fillComBoxValue(FileChooserUI fileChooserUI) {
        // 调用接口获取下拉框的中的值
        List<DictDataSource> dataSourceList = null;
        List<DictTarget> targetList = null;
        List<DictGather> gatherList = null;
        List<DictPwdFormat> pdwList = null;
        List<DictSystemModel> systemModelList = null;
        dataSourceList = dictDataSourceMapper.selectAll();
        targetList = dictTargetMapper.selectAll();
        gatherList = dictGatherMapper.selectAll();
        pdwList = dictPwdFormatMapper.selectAll();
        systemModelList = dictSystemModelMapper.selectAll();

        // 目标对象下拉框
        fileChooserUI.setDataSourceComboBox(new JComboBox<>());
        fileChooserUI.setTargetObjectComboBox(new JComboBox<>());
        fileChooserUI.setPdwComboBox(new JComboBox<>());
        fileChooserUI.setGatherPlaceComboBox(new JComboBox<>());
        fileChooserUI.setSystemModelComboBox(new JComboBox<>());

        for (DictDataSource dataSource : dataSourceList) {
            fileChooserUI.getDataSourceComboBox().addItem(dataSource);
        }
        for (DictTarget target : targetList) {
            fileChooserUI.getTargetObjectComboBox().addItem(target);
        }
        for (DictGather dictGather : gatherList) {
            fileChooserUI.getGatherPlaceComboBox().addItem(dictGather);
        }
        for (DictPwdFormat dictPwdFormat : pdwList) {
            fileChooserUI.getPdwComboBox().addItem(dictPwdFormat);
        }
        for (DictSystemModel dictSystemModel : systemModelList) {
            fileChooserUI.getSystemModelComboBox().addItem(dictSystemModel);
        }

        fileChooserUI.getDataSourceComboBox().setSelectedIndex(-1);
        fileChooserUI.getTargetObjectComboBox().setSelectedIndex(-1);
        fileChooserUI.getGatherPlaceComboBox().setSelectedIndex(-1);
        fileChooserUI.getPdwComboBox().setSelectedIndex(-1);
        fileChooserUI.getSystemModelComboBox().setSelectedIndex(-1);
    }

    /**
     * 开始上传文件逻辑
     */
    public void startUpload(FileChooserUI fileChooserUI) {
        // 使用 SwingWorker 执行后台任务 将 HTTP 请求放在一个独立的线程中执行，以避免阻塞主线程。
        scheduler.execute(() -> doInBackground(fileChooserUI));
    }

    private void doInBackground(FileChooserUI fileChooserUI) {
        String folderPath = fileChooserUI.folderPathField.getText().trim();// 落盘文件目录

        if (folderPath.isEmpty()) {
            JOptionPane.showMessageDialog(null, "请先选择要上传的文件目录！", "Error", JOptionPane.ERROR_MESSAGE);
            return;
        }
        DictSystemModel systemModelSelected = (DictSystemModel) systemModelComboBox.getSelectedItem();
        if (systemModelSelected == null) {
            JOptionPane.showMessageDialog(null, "请选择数据所属系统型号！", "Error", JOptionPane.ERROR_MESSAGE);
            return;
        }

        fileChooserUI.getSpeedLabel().setText(null);
        fileChooserUI.getTakeTimeLabel().setText(null);

        log.info("开始落盘");
        JButton sendButton = fileChooserUI.getSendButton();
        Timer sendUploadMsgTimer = fileChooserUI.getSendUploadMsgTimer();
        sendButton.setText("正在上传");
        sendButton.setEnabled(false);
        // 开启定时器
        sendUploadMsgTimer.start();

        // 字典数据
        DictDataSource dataSourceSelected = (DictDataSource) dataSourceJComboBox.getSelectedItem();
        DictTarget targetSelected = (DictTarget) targetObjectComboBox.getSelectedItem();
        DictPwdFormat pdwSelected = (DictPwdFormat) pdwComboBox.getSelectedItem();
        DictGather gatherSelected = (DictGather) gatherPlaceComboBox.getSelectedItem();
//        DictSystemModel systemModelSelected = (DictSystemModel) systemModelComboBox.getSelectedItem();


        FileMetaDataVO fileMetaDataVO = new FileMetaDataVO();
        fileMetaDataVO.setDirPath(folderPath);
        fileMetaDataVO.setDictDataSource(dataSourceSelected);
        fileMetaDataVO.setDictGather(gatherSelected);
        fileMetaDataVO.setDictPwdFormat(pdwSelected);
        fileMetaDataVO.setSystemModel(systemModelSelected);
        fileMetaDataVO.setDictTarget(targetSelected);
        fileMetaDataVO.setTaskName(fileChooserUI.taskNameField.getText());
        fileMetaDataVO.setProcessLog(fileChooserUI.getProcessLogField().getText());
        fileMetaDataVO.setCustomColumns(fileChooserUI.getCustomColumnVs());

        // 调用方法，开始落盘文件（同步的）
        ResponseResult response = placingFilesService.placingFile(fileMetaDataVO, fileChooserUI.getUnFinishedTaskId());

        log.info("上传完毕=======");
        sendUploadMsgTimer.stop();
        JOptionPane.showMessageDialog(null, response.getMessage(), "结果", JOptionPane.INFORMATION_MESSAGE);

        sendButton.setText("开始上传");
        sendButton.setEnabled(true);

        UploadMsgVO uploadMsg = fileChooserUI.getUploadMsg();
        if (uploadMsg == null)
            uploadMsg = new UploadMsgVO(fileChooserUI.taskNameField.getText(), 100, fileChooserUI.fileNums, fileChooserUI.fileTotalSizeLabel.getText(), fileChooserUI.leftTimeLabel.getText());
        uploadMsg.setProcess(100);
        webSocketClient.send(JSON.toJSONString(uploadMsg));
        log.info("通知后台100进度=======");


    }

    public void recordUnFinishTask(FileChooserUI fileChooserUI) {

        log.info("Performing data recording tasks before shutdown...");
        PlacingFileTask oldTask = placingFileTaskMapper.selectByTaskName(fileChooserUI.taskNameField.getText());

        if (fileChooserUI.progressBar.getValue() > 0
                && fileChooserUI.progressBar.getValue() < 100) { // 落盘任务还没完成
            PlacingFileTask placingFileTask = new PlacingFileTask(fileChooserUI);

            // 删除旧的未完成任务
            if (oldTask != null)
                placingFileTaskMapper.deleteByPrimaryKey(oldTask.getId());

            placingFileTaskMapper.insert(placingFileTask);
        }

    }
}
